#include <iostream>
#include "evnetplus/udp/udp_server.h"
#include "evnetplus/event_loop.h"
#include "evnetplus/event_loop_thread_pool.h"
#include "evnetplus/tcp_server_plus.h"

using namespace std;
using namespace evnetplus;

class TransmitTCPSession : public TCPSession
{
public:
    TransmitTCPSession(const TCPConnPtr& conn)
        : TCPSession(conn) {}
    ~TransmitTCPSession() {}

    virtual void onReceive(const std::string &buf) override {
        std::cout << "received bytes : " << buf.length() << std::endl;
        send(buf);
    }

    virtual void onConnected() override {
        std::cout << "new connection : " << remoteAddr() << std::endl;
    }

    virtual void onDisconnected() override {
        std::cout << "remote '"<< remoteAddr() << "' is disconnected." << std::endl;
    }

    virtual void onTimerHandle() override {

    }
};

int main(int argc, char const *argv[])
{
    udp::Server::Ptr udpserver = udp::Server::Ptr(new udp::Server);
    udpserver->SetThreadDispatchPolicy(ThreadDispatchPolicy::kIPAddressHashing);
    udpserver->SetMessageHandler([](EventLoop* loop, udp::MessagePtr& msg) {
        std::cout << "func=" << __FUNCTION__ << " OK"
            << " body=" << std::string(msg->data(), msg->size()) << "\n";
        udp::SendMessage(msg);
    });
    udpserver->Init(11450);
    udpserver->Start();

    EventLoopThread baseloopthread;
    baseloopthread.Start(true);
    EventLoopThreadPool::Ptr loopthreadpool = EventLoopThreadPool::Ptr(new EventLoopThreadPool(baseloopthread.loop(), 4));
    udpserver->SetEventLoopThreadPool(loopthreadpool);
    loopthreadpool->Start(true);


    TCPServerPlus::Ptr server = make_shared<TCPServerPlus>(baseloopthread.loop(), "0.0.0.0:9600", "PusherTcpServer");
    if (server == nullptr) {
        fprintf(stderr, "pusher tcp server create failed.\n");
        return -1;
    }
    bool ret = server->start<TransmitTCPSession>();


    bool bEnableStop = false;
    SignalEventWatcher signalWatcher(SIGINT, baseloopthread.loop(), [&bEnableStop](){
        std::cout << "atched signal" << std::endl;
        bEnableStop = true;
    });
    signalWatcher.Init();
    signalWatcher.AsyncWait();

    while (!bEnableStop) {
        this_thread::sleep_for(chrono::milliseconds(500));
    }

    udpserver->Stop(true);
    server->stop();
    loopthreadpool->Stop();
    baseloopthread.Stop(true);

    return 0;
}
